package com.qiye.livevideo.controller;

import com.aliyuncs.live.model.v20161101.DescribeLivePullStreamConfigResponse;
import com.aliyuncs.live.model.v20161101.DescribeLiveStreamsOnlineListResponse;
import com.aliyuncs.live.model.v20161101.DescribeLiveStreamsPublishListResponse;
import com.qiye.livevideo.common.CodeMsg;
import com.qiye.livevideo.common.ResultInfo;
import com.qiye.livevideo.common.RetConstant;
import com.qiye.livevideo.config.aop.ControllerApiCall;
import com.qiye.livevideo.model.AliCloudLiveInfo;
import com.qiye.livevideo.service.AliCloudLiveInfoService;
import com.qiye.livevideo.utils.AliLivePullFlowUtils;
import com.qiye.livevideo.utils.AliLivePushFlowUtils;
import com.qiye.livevideo.utils.AliLiveSdkUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;

/**
 * Created on 2019/4/30.
 *
 * @author meishijun
 */
@Api(description = "直播API")
@Controller
@RequestMapping(value = "/LiveBroadcast")
public class LiveBroadcastController {
    private static final Logger log = LoggerFactory.getLogger(LiveBroadcastController.class);
    @Resource
    private AliCloudLiveInfoService aliCloudLiveInfoService;

    /**
     * 根据阿里云的唯一标识应用名称和流名称获取推拉流地址
     * @param format
     * @param appName
     * @param streamName
     * @param minute
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping("/getLiveFlowAddress")
    @ApiOperation(value = "获取推拉流地址", notes = "根据应用名称及流名称获取", httpMethod = "POST")
    public ResultInfo selectByPrimaryKey(@ApiParam(name = "accessKeyId", value = "AccessKeyId是类似身份的标识") @RequestParam(required = false) String accessKeyId,
                                         @ApiParam(name = "format", value = "播流地址格式，0为获取全部格式，1为rtmp 2为flv 3为m3u8", required = true) @RequestParam String format,
                                         @ApiParam(name = "appName", value = "应用名称", required = true) @RequestParam String appName,
                                         @ApiParam(name = "streamName", value = "流名称", required = true) @RequestParam String streamName,
                                         @ApiParam(name = "minute", value = "有效分钟数", required = true) @RequestParam Integer minute, HttpServletRequest request, HttpServletResponse response) {

        //校验
        if (accessKeyId == null || accessKeyId.isEmpty()) {
            //如果身份标识为空，设置一个默认身份标识
            accessKeyId = RetConstant.DEFAULT_ACCESS_KEY_ID;
        }
        if (format == null || format.isEmpty()) {
            return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "播流格式不能为空!");
        } else {
            if (RetConstant.FROMAT_FLOW_RTMP.equals(format)) {
                format = "rtmp";
            }
            if (RetConstant.FROMAT_FLOW_FLV.equals(format)) {
                format = "flv";
            }
            if (RetConstant.FROMAT_FLOW_M3U8.equals(format)) {
                format = "m3u8";
            }
        }
        if (appName == null || appName.isEmpty()) {
            return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "应用名称不能为空!");
        }
        if (streamName == null || streamName.isEmpty()) {
            return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "流名称不能为空!");
        }
        if (minute == null || minute <= 0) {
            return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "有效分钟数不能为空且不能小于等于0!");
        }
        Long time = dataToStamp(minute);
        List<String> list = new ArrayList<String>();
        //根据身份唯一标识查询数据库中阿里云信息
        AliCloudLiveInfo aliCloudLiveInfo = aliCloudLiveInfoService.selectByaccessKeyId(accessKeyId);
        if(aliCloudLiveInfo==null){
            return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "没有查询到该阿里云的账号信息!");
        }else {
            list.add("推流地址:" + AliLivePushFlowUtils.getPushUrl(appName, streamName, time,accessKeyId));
            if (RetConstant.FROMAT_FLOW_ALL.equals(format)) {
                list.add("播流地址rtmp:" + AliLivePullFlowUtils.getPullUrl("rtmp", appName, streamName, time,accessKeyId));
                list.add("播流地址flv:" + AliLivePullFlowUtils.getPullUrl("flv", appName, streamName, time,accessKeyId));
                list.add("播流地址m3u8:" + AliLivePullFlowUtils.getPullUrl("m3u8", appName, streamName, time,accessKeyId));
            } else {
                list.add("播流地址" + format + ":" + AliLivePullFlowUtils.getPullUrl(format, appName, streamName, time,accessKeyId));
            }
        }
        return ResultInfo.success(list);
    }

    /**
     * 获取已经推流结束的推流记录
     *
     * @param appName
     * @param domainName
     * @param streamName
     * @param startTime
     * @param endTime
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping("/getLiveFlowList")
    @ApiOperation(value = "根据时间段获取该时间段内的推流记录", notes = "域名和时间为必填项", httpMethod = "POST")
    public ResultInfo getLiveFlowList(@ApiParam(name = "accessKeyId", value = "AccessKeyId是类似身份的标识") @RequestParam(required = false) String accessKeyId,
                                      @ApiParam(name = "appName", value = "应用名称") @RequestParam(required = false) String appName,
                                      @ApiParam(name = "domainName", value = "域名", required = true) @RequestParam String domainName,
                                      @ApiParam(name = "streamName", value = "流名称") @RequestParam(required = false) String streamName,
                                      @ApiParam(name = "startTime", value = "开始时间", required = true) @RequestParam String startTime,
                                      @ApiParam(name = "endTime", value = "结束时间", required = true) @RequestParam String endTime,
                                      HttpServletRequest request, HttpServletResponse response) {
        try {
            if (accessKeyId == null || accessKeyId.isEmpty()) {
                //如果身份标识为空，设置一个默认身份标识
                accessKeyId = RetConstant.DEFAULT_ACCESS_KEY_ID;
            }
            //判断域名不能为空
            if (domainName == null || domainName.isEmpty()) {
                return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "域名不能为空");
            }
            //判断开始时间与结束时间
            if (startTime == null || startTime.isEmpty()) {
                return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "开始时间不能为空");
            }
            if (endTime == null || endTime.isEmpty()) {
                return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "结束时间不能为空");
            }
            //转换时间格式
            //UTC格式与标准格式之间转换
            SimpleDateFormat utc = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
            //设置时区
            utc.setTimeZone(TimeZone.getTimeZone("UTC"));
            SimpleDateFormat standard = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String utcStatrtStr = utc.format(standard.parse(startTime));
            String utcEndStr = utc.format(standard.parse(endTime));
            DescribeLiveStreamsPublishListResponse responseInfo = new DescribeLiveStreamsPublishListResponse();
            //根据身份唯一标识查询数据库中阿里云信息
            AliCloudLiveInfo aliCloudLiveInfo = aliCloudLiveInfoService.selectByaccessKeyId(accessKeyId);
            if(aliCloudLiveInfo==null){
                return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "没有查询到该阿里云的账号信息!");
            }else {
                String accessKeySeret = aliCloudLiveInfo.getAccessKeySeret();
                if(accessKeySeret==null || accessKeySeret.isEmpty()){
                    return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "该阿里云的账号的accessKeySeret为空，请联系管理员!");
                }
                responseInfo = AliLiveSdkUtils.getFlowList(domainName, appName, streamName, utcStatrtStr, utcEndStr,accessKeyId,accessKeySeret);
            }
            return ResultInfo.success(responseInfo);
        } catch (Exception e) {
            log.error("查询推流记录失败："+ System.getProperty("line.separator", "\n") + "参数信息："
                    + System.getProperty("line.separator", "\n") + "appName:" + appName
                    + System.getProperty("line.separator", "\n") + "domainName:" + domainName
                    + System.getProperty("line.separator", "\n") + "streamName:" + streamName
                    + System.getProperty("line.separator", "\n") + "startTime:" + startTime
                    + System.getProperty("line.separator", "\n") + "endTime:" + endTime
                    + System.getProperty("line.separator", "\n") + "具体异常信息：",e.getMessage());
            return ResultInfo.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }
    }


    /**
     * 获取当前正在推流的信息=======（基于Aop限制次数每分钟调用不能超过1000次）
     *
     * @param appName
     * @param domainName
     * @param streamName
     * @param request
     * @param response
     * @return
     */
    @ControllerApiCall
    @ResponseBody
    @RequestMapping("/getLiveNowFlowList")
    @ApiOperation(value = "获取当前的推流信息", notes = "阿里云建议该接口每分钟调用不要超过1000次", httpMethod = "POST")
    public ResultInfo getLiveNowFlowList(@ApiParam(name = "accessKeyId", value = "AccessKeyId是类似身份的标识") @RequestParam(required = false) String accessKeyId,
                                         @ApiParam(name = "appName", value = "应用名称") @RequestParam(required = false) String appName,
                                         @ApiParam(name = "domainName", value = "域名", required = true) @RequestParam String domainName,
                                         @ApiParam(name = "streamName", value = "流名称") @RequestParam(required = false) String streamName,
                                         HttpServletRequest request, HttpServletResponse response) {
        try {
            if (accessKeyId == null || accessKeyId.isEmpty()) {
                //如果身份标识为空，设置一个默认身份标识
                accessKeyId = RetConstant.DEFAULT_ACCESS_KEY_ID;
            }
            //判断域名不能为空
            if (domainName == null || domainName.isEmpty()) {
                return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "域名不能为空");
            }
            DescribeLiveStreamsOnlineListResponse responseInfo =new DescribeLiveStreamsOnlineListResponse();
            //根据身份唯一标识查询数据库中阿里云信息
            AliCloudLiveInfo aliCloudLiveInfo = aliCloudLiveInfoService.selectByaccessKeyId(accessKeyId);
            if(aliCloudLiveInfo==null){
                return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "没有查询到该阿里云的账号信息!");
            }else {
                String accessKeySeret = aliCloudLiveInfo.getAccessKeySeret();
                if(accessKeySeret==null || accessKeySeret.isEmpty()){
                    return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "该阿里云的账号的accessKeySeret为空，请联系管理员!");
                }
                responseInfo = AliLiveSdkUtils.getNowFlowList(domainName, appName, streamName,accessKeyId,accessKeySeret);
            }

            return ResultInfo.success(responseInfo);
        }catch (Exception e){
            log.error("查询推流记录失败："+ System.getProperty("line.separator", "\n") + "参数信息："
                    + System.getProperty("line.separator", "\n") + "appName:" + appName
                    + System.getProperty("line.separator", "\n") + "domainName:" + domainName
                    + System.getProperty("line.separator", "\n") + "streamName:" + streamName
                    + System.getProperty("line.separator", "\n") + "具体异常信息：",e.getMessage());
            return ResultInfo.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }
    }



    /**
     * 获取域名下的拉流配置信息列表---指用户已关闭的拉流信息（可以基于这个接口查看直播访问量)
     *
     * @param domainName
     * @param request
     * @param response
     * @return
     */
    @ControllerApiCall
    @ResponseBody
    @RequestMapping("/getLivePullFlowConfigList")
    @ApiOperation(value = "获取域名下的拉流配置信息列表", httpMethod = "POST")
    public ResultInfo getLivePullFlowConfigList(@ApiParam(name = "accessKeyId", value = "AccessKeyId是类似身份的标识") @RequestParam(required = false) String accessKeyId,
                                                @ApiParam(name = "domainName", value = "域名", required = true) @RequestParam String domainName,
                                                HttpServletRequest request, HttpServletResponse response) {
        try {
            if (accessKeyId == null || accessKeyId.isEmpty()) {
                //如果身份标识为空，设置一个默认身份标识
                accessKeyId = RetConstant.DEFAULT_ACCESS_KEY_ID;
            }
            //判断域名不能为空
            if (domainName == null || domainName.isEmpty()) {
                return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "域名不能为空");
            }
            DescribeLivePullStreamConfigResponse responseInfo = new DescribeLivePullStreamConfigResponse();
            //根据身份唯一标识查询数据库中阿里云信息
            AliCloudLiveInfo aliCloudLiveInfo = aliCloudLiveInfoService.selectByaccessKeyId(accessKeyId);
            if(aliCloudLiveInfo==null){
                return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "没有查询到该阿里云的账号信息!");
            }else {
                String accessKeySeret = aliCloudLiveInfo.getAccessKeySeret();
                if(accessKeySeret==null || accessKeySeret.isEmpty()){
                    return ResultInfo.error(CodeMsg.PARAMETER_ISNULL, "该阿里云的账号的accessKeySeret为空，请联系管理员!");
                }
                responseInfo = AliLiveSdkUtils.getLiveNowFlowList(domainName,accessKeyId,accessKeySeret);
            }
            return ResultInfo.success(responseInfo);
        }catch (Exception e){
            log.error("查询推流记录失败："+ System.getProperty("line.separator", "\n") + "参数信息："
                    + System.getProperty("line.separator", "\n") + "domainName:" + domainName
                    + System.getProperty("line.separator", "\n") + "具体异常信息：",e.getMessage());
            return ResultInfo.error(CodeMsg.SERVER_EXCEPTION, e.getMessage());
        }
    }


    /**
     * 将有效时间时间转换成时间戳
     * @param minute
     * @return
     */
    private Long dataToStamp(int minute) {
        Long time = System.currentTimeMillis();
        //在当前系统的基础上增加分钟数。即
        time += minute * 1000 * 60;
        return time / 1000;
    }
}
